package com.example.rbacmanage.interceptor;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.druid.util.StringUtils;
import com.example.rbacmanage.annotation.PassFrontToken;
import com.example.rbacmanage.common.Constant;
import com.example.rbacmanage.entity.AppUser;
import com.example.rbacmanage.exception.MyException;
import com.example.rbacmanage.mapper.AppUserMapper;
import com.example.rbacmanage.util.JwtTokenUtil;
import com.example.rbacmanage.util.SpringUtils;
import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class AppInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return false;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        //无须授权
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(PassFrontToken.class)) {
            return true;
        }

        //是否携带token，没有则返回并响应
        String token = request.getHeader("AuthorizationappUser");
        if (StringUtils.isEmpty(token)){
            throw new MyException("token not found",HttpStatus.UNAUTHORIZED.value());
        }

        //token是否存在
        String userId = JwtTokenUtil.getUsernameFromToken(token);
        if (userId == null){
            throw new MyException("token not exist",HttpStatus.UNAUTHORIZED.value());
        }

        //redis缓存是否存在
        RedisTemplate redisTemplate=SpringUtils.getBean("redisTemplate");
        if (!redisTemplate.hasKey(Constant.appLoginUserToken +userId)){
            throw new MyException("token not exist",HttpStatus.UNAUTHORIZED.value());
        }

        //是否与缓存一致
        if (!redisTemplate.opsForValue().get(Constant.appLoginUserToken+userId).equals(token)){
            throw new MyException("token expired",HttpStatus.UNAUTHORIZED.value());
        }

        //判断token是否过期
        Date date = JwtTokenUtil.getExpiredDateFromToken(token);
        if (new Date().compareTo(date) > 0){
            throw new MyException("token expired",HttpStatus.UNAUTHORIZED.value());
        }

        //没有携带前台登录用户id,拦截
        Parameter[] parameters = method.getParameters();
        if (parameters.length == 0 //参数为空
                || !parameters[0].getParameterizedType().equals(Long.class)
        ) {
            return false;
        }

        //用户是否存在
        System.out.println("web拦截器");

        System.out.println("token:"+token);

        //用户是否存在
        AppUserMapper blogAppUserMapper = SpringUtils.getBean("appUserMapper");
        AppUser blogAppUser = blogAppUserMapper.queryOneById(Long.valueOf(userId));
        if (blogAppUser == null){
            try {
                Map<String,Object> map = new HashMap<>();
                map.put("code",500);
                map.put("msg","用户不存在");
                response.getWriter().write(JSONUtils.toJSONString(map));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return false;
        }
        //判断请求参数是否包含敏感词汇
        Map<String,String[]> parameterMap = request.getParameterMap();
        for (String key : parameterMap.keySet()) {
            if (key.equals("t")){
                continue;
            }
            String[] values = parameterMap.get(key);
            for (String value : values) {
                if ( !StringUtils.isEmpty(value) && SensitiveWordHelper.contains(value)) {
                    // 如果包含敏感词，可以抛出异常或者返回错误响应
                    throw new MyException("包含敏感词汇"+SensitiveWordHelper.findFirst(value)+"，请重新输入",HttpStatus.BAD_REQUEST.value());
                }
            }
        }
        return true;
    }
}
